{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%matplotlib inline"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "对于网络的训练和测试，首先需要定义网络，自己定义了一个简单的网络如下:\n",
    "---"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "import os\n",
    "import math\n",
    "import torch\n",
    "import torch.nn as nn\n",
    "import simple_utils"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "class ACNN(nn.Module):\n",
    "    '''ACNN 自己创建的神经网络，用于识别面部表情\n",
    "\n",
    "        n_class 表示输出的分类数\n",
    "    '''\n",
    "    def __init__(self, n_classes=7):\n",
    "        # nn.Module子类的函数必须在构造函数中执行父类的构造函数\n",
    "        super(ACNN, self).__init__()\n",
    "        self.input_size = 96  # 输入96*96大小的图片\n",
    "        self.features = nn.Sequential(\n",
    "            nn.Conv2d(in_channels=1, out_channels=64, kernel_size=9, stride=1),  # 64, 88, 88\n",
    "            nn.ReLU(inplace=True),\n",
    "            nn.MaxPool2d(kernel_size=2, stride=2),  # 64, 44, 44\n",
    "            nn.Conv2d(in_channels=64, out_channels=64, kernel_size=7, stride=1),  # 64, 38, 38\n",
    "            nn.ReLU(inplace=True),\n",
    "            nn.Conv2d(in_channels=64, out_channels=64, kernel_size=7, stride=1),  # 64, 32, 32\n",
    "            nn.ReLU(inplace=True),\n",
    "            nn.MaxPool2d(kernel_size=2, stride=1),  # 64, 31, 31\n",
    "            nn.Conv2d(in_channels=64, out_channels=64, kernel_size=5, stride=1),  # 64, 27, 27\n",
    "            nn.ReLU(inplace=True),\n",
    "            nn.Conv2d(in_channels=64, out_channels=64, kernel_size=5, stride=1),  # 64, 23, 23\n",
    "            nn.ReLU(inplace=True),\n",
    "            nn.MaxPool2d(kernel_size=2, stride=1),  # 64, 22, 22\n",
    "            nn.Conv2d(in_channels=64, out_channels=64, kernel_size=3, stride=1),  # 64, 20, 20\n",
    "            nn.ReLU(inplace=True),\n",
    "            nn.Conv2d(in_channels=64, out_channels=64, kernel_size=3, stride=1),  # 64, 18, 18\n",
    "            nn.ReLU(inplace=True),\n",
    "            nn.MaxPool2d(kernel_size=2, stride=1),  # 64, 17, 17\n",
    "            nn.Conv2d(in_channels=64, out_channels=64, kernel_size=3, stride=1),  # 64, 15, 15\n",
    "            nn.ReLU(inplace=True),\n",
    "            nn.Conv2d(in_channels=64, out_channels=64, kernel_size=3, stride=1),  # 64, 13, 13\n",
    "            nn.ReLU(inplace=True),\n",
    "            nn.MaxPool2d(kernel_size=2, stride=1),  # 64, 12, 12\n",
    "        )\n",
    "        self.classifier = nn.Sequential(\n",
    "            nn.Dropout(p=0.6),\n",
    "            nn.Linear(64 * 12 * 12, n_classes),\n",
    "            nn.Softmax(1),\n",
    "        )\n",
    "        self._initialize_weights()\n",
    "\n",
    "    def forward(self, x):\n",
    "        # 通过特征层\n",
    "        x = self.features(x)\n",
    "        # 压成1维\n",
    "        x = x.view(-1, self.num_flat_features(x))\n",
    "        # 通过全连接层并经过Softmax\n",
    "        x = self.classifier(x)\n",
    "        return x\n",
    "\n",
    "    def num_flat_features(self, x):\n",
    "        '''获取扁平后的特征数量'''\n",
    "        size = x.size()[1:]  # all dimensions except the batch dimension\n",
    "        num_features = 1\n",
    "        for s in size:\n",
    "            num_features *= s\n",
    "        return num_features\n",
    "\n",
    "    def _initialize_weights(self):\n",
    "        '''初始化权重，可以自己定义，可以不定义'''\n",
    "        for layer in self.named_modules():\n",
    "            if isinstance(layer[1], nn.Conv2d):\n",
    "                n = layer[1].kernel_size[0] * layer[1].kernel_size[1] * layer[1].out_channels\n",
    "                layer[1].weight.data.normal_(0, math.sqrt(2. / n))\n",
    "                if layer[1].bias is not None:\n",
    "                    layer[1].bias.data.zero_()\n",
    "            elif isinstance(layer[1], nn.Linear):\n",
    "                layer[1].weight.data.normal_(0, 0.01)\n",
    "                layer[1].bias.data.zero_()\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "net = ACNN(7)\n",
    "print(net)\n",
    "simple_utils.num_of_parameters_of_net(net)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "网络定义完成后，就可以用封装好的数据集进行训练了\n",
    "---"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "cuda available:  True\n",
      "using DEVICE:  cuda\n"
     ]
    }
   ],
   "source": [
    "# coding=utf-8\n",
    "import os\n",
    "import torch\n",
    "import torch.optim\n",
    "from torch.autograd import Variable\n",
    "import torch.nn as nn\n",
    "import numpy as np\n",
    "import argparse\n",
    "import time\n",
    "\n",
    "from CKPlus_DataSet import CKPlus\n",
    "from VGG import *\n",
    "import transforms.transforms as transforms\n",
    "import simple_utils as utils\n",
    "\n",
    "use_cuda = torch.cuda.is_available()\n",
    "DEVICE = torch.device(\"cuda\" if use_cuda else \"cpu\")  # 让torch判断是否使用GPU，建议使用GPU环境，因为会快很多\n",
    "print('cuda available: ', use_cuda)\n",
    "print('using DEVICE: ', DEVICE)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 如果在 .py 文件中，则可以如下定义，从命令行执行的时候，根据 --Variabels 来指定参数\n",
    "# parser = argparse.ArgumentParser(description='PyTorch CNN Training With JAFFE')\n",
    "# # 存储的模型序号\n",
    "# parser.add_argument('--save_number', default=1, type=int, help='save_number')\n",
    "# # 批次大小\n",
    "# parser.add_argument('--bs', default=4, type=int, help='batch_size')\n",
    "# # 学习率\n",
    "# parser.add_argument('--lr', default=0.01, type=float, help='learning rate')\n",
    "# # epoch\n",
    "# parser.add_argument('--epoch', default=200, type=int, help='training epoch num')\n",
    "# # 每次获得到更优的准确率后，会进行一次存储，此选项选择是否从上次存储位置继续\n",
    "# parser.add_argument('--resume', default=True, type=bool, help='resume training from last checkpoint')\n",
    "# 表示默认从第 $lrd_se 次epoch开始进行lr的递减\n",
    "# parser.add_argument('--lrd_se', default=180, type=int, help='learning rate decay start epoch')\n",
    "# 表示默认每经过2次epoch进行一次递减\n",
    "# parser.add_argument('--lrd_s', default=2, type=int, help='learning rate decay step')\n",
    "# 表示每次的lr的递减率，默认每递减一次乘一次0.9\n",
    "# parser.add_argument('--lrd_r', default=0.9, type=float, help='learning rate decay rate')\n",
    "# opt = parser.parse_args()\n",
    "\n",
    "# 在这里使用一个类进行替代\n",
    "class OPT:\n",
    "    def __init__(self):\n",
    "        # 存储的模型序号\n",
    "        self.save_number = 1\n",
    "        # 批次大小\n",
    "        self.bs = 4\n",
    "        # 学习率\n",
    "        self.lr = 0.008\n",
    "        # epoch\n",
    "        self.epoch = 200\n",
    "        # 每次获得到更优的准确率后，会进行一次存储，此选项选择是否从上次存储位置继续\n",
    "        self.resume = False\n",
    "        self.dataset = \"CKPlus\"\n",
    "        # 表示默认从第 $lrd_se 次epoch开始进行lr的递减\n",
    "        self.lrd_se = 100\n",
    "        # 表示默认每经过2次epoch进行一次递减\n",
    "        self.lrd_s = 10\n",
    "        # 表示每次的lr的递减率，默认每递减一次乘一次0.9\n",
    "        self.lrd_r = 0.9\n",
    "opt = OPT()\n",
    "\n",
    "train_acc_map = {'best_acc': 0, 'best_acc_epoch': -1}\n",
    "test_acc_map = {'best_acc': 0, 'best_acc_epoch': -1}\n",
    "Train_acc, Test_acc = 0., 0."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "------------Preparing Data...----------------\n",
      "train_num:  906  test_num: 75\n",
      "train_num:  906  test_num: 75\n",
      "------------CKPlus Data Already be Prepared------------\n"
     ]
    }
   ],
   "source": [
    "print(\"------------Preparing Data...----------------\")\n",
    "train_data = CKPlus(is_train=True, img_dir_pre_path=\"data/CK+\")\n",
    "test_data = CKPlus(is_train=False, img_dir_pre_path=\"data/CK+\")\n",
    "print(\"------------%s Data Already be Prepared------------\" % opt.dataset)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "------------Preparing Model...----------------\n",
      "------------Model Already be Prepared------------\n"
     ]
    }
   ],
   "source": [
    "print(\"------------Preparing Model...----------------\")\n",
    "n_classes = 7\n",
    "net_to_save_dir = \"Saved_Models\"\n",
    "net_to_save_path = os.path.join(net_to_save_dir, str(opt.save_number),\n",
    "                                opt.dataset + '_' + str(opt.save_number))\n",
    "saved_model_name = \"Best_model.t7\"\n",
    "saved_temp_model_name = \"Best_model_temp.t7\"\n",
    "model_over_flag_name = \"__%d_success__\" % (opt.epoch)\n",
    "history_file_name = \"history.txt\"\n",
    "\n",
    "over_flag = False  # 如果已经成功训练完，就可以结束了\n",
    "TEMP_EPOCH = 5  # 用于暂时存储，每TEMP_EPOCH次存一次\n",
    "temp_internal = TEMP_EPOCH\n",
    "\n",
    "# net = ACNN(n_classes=n_classes).to(DEVICE)\n",
    "net = vgg11_bn(n_classes=n_classes).to(DEVICE)\n",
    "\n",
    "start_epoch = 0\n",
    "if opt.resume:\n",
    "    # Load checkpoint.\n",
    "    print('==> Loading Model Parameters...')\n",
    "    if os.path.exists(os.path.join(net_to_save_path, saved_temp_model_name)):\n",
    "        if os.path.exists(os.path.join(net_to_save_path, model_over_flag_name)):\n",
    "            print(\"Model trained over flag checked!\")\n",
    "            over_flag = True\n",
    "        assert os.path.isdir(net_to_save_path), 'Error: no checkpoint directory found!'\n",
    "        checkpoint = torch.load(os.path.join(net_to_save_path, saved_temp_model_name))\n",
    "        net.load_state_dict(checkpoint['net'])\n",
    "        test_acc_map['best_acc'] = checkpoint['best_test_acc']\n",
    "        test_acc_map['best_acc_epoch'] = checkpoint['best_test_acc_epoch']\n",
    "        start_epoch = checkpoint['cur_epoch'] + 1\n",
    "    else:\n",
    "        print(\"Checkout File not Found, No initialization.\")\n",
    "print(\"------------Model Already be Prepared------------\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [],
   "source": [
    "input_img_size = net.input_size\n",
    "\n",
    "IMG_MEAN = [0.5]\n",
    "IMG_STD = [0.225]\n",
    "transform_train = transforms.Compose([\n",
    "    transforms.Resize(input_img_size),  # 缩放将图片的最小边缩放为 input_img_size，因此如果输入是非正方形的，那么输出也不是正方形的\n",
    "    transforms.CenterCrop(input_img_size),\n",
    "    transforms.RandomHorizontalFlip(),\n",
    "    transforms.RandomRotation(30),\n",
    "    transforms.ToTensor(),\n",
    "    transforms.Normalize(IMG_MEAN, IMG_STD),\n",
    "])\n",
    "transform_test = transforms.Compose([\n",
    "    transforms.Resize(input_img_size),  # 缩放将图片的最小边缩放为 input_img_size，因此如果输入是非正方形的，那么输出也不是正方形的\n",
    "    transforms.CenterCrop(input_img_size),\n",
    "    transforms.ToTensor(),\n",
    "    transforms.Normalize(IMG_MEAN, IMG_STD),\n",
    "])\n",
    "train_data.set_transform(transform_train)\n",
    "test_data.set_transform(transform_test)\n",
    "train_loader = torch.utils.data.DataLoader(train_data, batch_size=opt.bs, shuffle=True)\n",
    "test_loader = torch.utils.data.DataLoader(test_data, batch_size=opt.bs, shuffle=False)\n",
    "# 交叉熵损失函数\n",
    "criterion = nn.CrossEntropyLoss()\n",
    "# 随机梯度下降 优化\n",
    "optimizer = torch.optim.SGD(net.parameters(), lr=opt.lr, momentum=0.9, weight_decay=5e-4)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Training\n",
    "def train(epoch):\n",
    "    # 根据训练的epoch次数来降低learning rate\n",
    "    if epoch >= opt.lrd_se > 0:\n",
    "        frac = ((epoch - opt.lrd_se) // opt.lrd_s) + 1\n",
    "        decay_factor = opt.lrd_r ** frac\n",
    "        current_lr = opt.lr * decay_factor  # current_lr = opt.lr * 降低率 ^ ((epoch - 开始decay的epoch) // 每次decay的epoch num)\n",
    "        utils.set_lr(optimizer, current_lr)  # set the learning rate\n",
    "    else:\n",
    "        current_lr = opt.lr\n",
    "    print('learning_rate: %s' % str(current_lr))\n",
    "    \n",
    "    global Train_acc\n",
    "    net.train()\n",
    "    train_loss = 0\n",
    "    correct = 0\n",
    "    total = 0\n",
    "    cur_train_acc = 0.\n",
    "    time_start = time.time()\n",
    "    for batch_idx, (inputs, targets) in enumerate(train_loader):\n",
    "        optimizer.zero_grad()  # 优化的梯度清零\n",
    "        if use_cuda:\n",
    "            inputs, targets = inputs.to(DEVICE), targets.to(DEVICE, torch.long)\n",
    "        outputs = net(inputs)\n",
    "        # print(\"outputs:\", outputs)\n",
    "        # print(\"targets:\", targets)\n",
    "        loss = criterion(outputs, targets)\n",
    "        loss.backward()\n",
    "        utils.clip_gradient(optimizer, 2*current_lr)  # 解决梯度爆炸 https://blog.csdn.net/u010814042/article/details/76154391\n",
    "        optimizer.step()\n",
    "\n",
    "        train_loss += float(loss.data)\n",
    "        _, predicted = torch.max(outputs.data, 1)  # torch.max() 加上dim参数后，返回值为 max_value, max_value_index\n",
    "        ground_value = targets.data\n",
    "        # print(\"predicted:\", predicted)\n",
    "        # print(\"ground_value:\", ground_value)\n",
    "\n",
    "        total += targets.size(0)\n",
    "        correct += predicted.eq(ground_value.data).cpu().sum()\n",
    "        # print(\"equal: \", predicted.eq(ground_value.data).cpu())\n",
    "        cur_train_acc = float(correct) / float(total) * 100.\n",
    "\n",
    "        time_end = time.time()\n",
    "        duration = time_end - time_start\n",
    "        utils.progress_bar(batch_idx, len(train_loader), 'Time: %.2fs | Loss: %.3f | Acc: %.3f%% (%d/%d)' %\n",
    "                           (duration, train_loss / (batch_idx + 1), cur_train_acc, correct, total))\n",
    "\n",
    "        # 删除无用的变量，释放显存\n",
    "        del loss\n",
    "        del inputs\n",
    "        del outputs\n",
    "        del predicted\n",
    "    Train_acc = cur_train_acc\n",
    "    write_history('Train', epoch, cur_train_acc, train_loss / (batch_idx + 1), None)\n",
    "\n",
    "# Testing\n",
    "def test(epoch):\n",
    "    global Test_acc\n",
    "    private_test_loss = 0\n",
    "    net.eval()\n",
    "    correct = 0\n",
    "    total = 0\n",
    "    cur_test_acc = 0.\n",
    "    correct_map = [0, 0, 0, 0, 0, 0, 0]\n",
    "    time_start = time.time()\n",
    "    with torch.no_grad():\n",
    "        for batch_idx, (inputs, targets) in enumerate(test_loader):\n",
    "            if use_cuda:\n",
    "                inputs, targets = inputs.to(DEVICE), targets.to(DEVICE, torch.long)\n",
    "            outputs = net(inputs)\n",
    "\n",
    "            loss = criterion(outputs, targets)\n",
    "            private_test_loss += float(loss.data)\n",
    "            _, predicted = torch.max(outputs.data, 1)\n",
    "            ground_value = targets.data\n",
    "\n",
    "            for i in range(len(predicted)):\n",
    "                if predicted[i] == ground_value[i]:\n",
    "                    correct_map[predicted[i].item()] += 1\n",
    "\n",
    "            total += targets.size(0)\n",
    "            correct += predicted.eq(ground_value.data).cpu().sum()\n",
    "            cur_test_acc = float(correct) / float(total) * 100.\n",
    "\n",
    "            time_end = time.time()\n",
    "            duration = time_end - time_start\n",
    "            utils.progress_bar(batch_idx, len(test_loader), 'Time: %.2fs | Loss: %.3f | Acc: %.3f%% (%d/%d)' %\n",
    "                               (duration, private_test_loss / (batch_idx + 1), cur_test_acc, correct, total))\n",
    "\n",
    "            # 删除无用的变量，释放显存\n",
    "            del loss\n",
    "            del inputs\n",
    "            del outputs\n",
    "            del predicted\n",
    "\n",
    "    Test_acc = cur_test_acc\n",
    "    if test_acc_map['best_acc'] < Test_acc:\n",
    "        train_acc_map['best_acc'] = Train_acc\n",
    "        train_acc_map['best_acc_epoch'] = epoch\n",
    "        test_acc_map['best_acc'] = Test_acc\n",
    "        test_acc_map['best_acc_epoch'] = epoch\n",
    "        print('Saving net to %s' % net_to_save_path)\n",
    "        print('best_acc: %0.3f' % test_acc_map['best_acc'])\n",
    "        print('correct_map: %s' % correct_map)\n",
    "        state = {'net': net.state_dict() if use_cuda else net,\n",
    "                 'best_test_acc': test_acc_map['best_acc'],\n",
    "                 'best_test_acc_epoch': test_acc_map['best_acc_epoch'],\n",
    "                 'best_train_acc': train_acc_map['best_acc'],\n",
    "                 'best_train_acc_epoch': train_acc_map['best_acc_epoch'],\n",
    "                 'cur_epoch': epoch,\n",
    "                 'correct_map': correct_map,\n",
    "                 }\n",
    "        torch.save(state, os.path.join(net_to_save_path, saved_model_name))\n",
    "    write_history('Test', epoch, cur_test_acc, private_test_loss / (batch_idx + 1), correct_map)\n",
    "\n",
    "\n",
    "def write_history(train_or_test, epoch, acc, loss, predictions):\n",
    "    '''\n",
    "    将数据写入history.txt文件保存\n",
    "    :param train_or_test: 训练过程还是测试过程（'Train' or 'Test'）\n",
    "    :param epoch: 迭代次数\n",
    "    :param acc: 准确率\n",
    "    :param loss: 损失\n",
    "    :param predictions: 预测情况\n",
    "    :return: 无\n",
    "    '''\n",
    "    with open(os.path.join(net_to_save_path, history_file_name), \"a+\", encoding=\"utf-8\") as history_file:\n",
    "        msg = train_or_test + \" %d %.3f %.3f \" % (epoch, acc, loss)\n",
    "        if predictions:\n",
    "            msg += str(predictions)\n",
    "        msg += \"\\n\"\n",
    "        history_file.write(msg)\n",
    "        history_file.flush()\n",
    "\n",
    "\n",
    "def save_over_flag():\n",
    "    '''\n",
    "    创建一个空文件表示训练完成\n",
    "    :return: 无\n",
    "    '''\n",
    "    file_path = os.path.join(net_to_save_path, model_over_flag_name)\n",
    "    with open(file_path, \"w+\", encoding=\"utf-8\") as file:\n",
    "        file.write(train_acc_map.__str__())\n",
    "        file.write(\"\\n\")\n",
    "        file.write(test_acc_map.__str__())\n",
    "        file.write(\"\\n\")\n",
    "        file.flush()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\n",
      "------------Epoch: 0-------------\n",
      "learning_rate: 0.008\n",
      "[==============================>] | Time: 62.02s | Loss: 4.014 | Acc: 18.874% (171/906)\n",
      "[==============================>] | Time: 1.21s | Loss: 1.837 | Acc: 28.000% (21/75)\n",
      "Saving net to Saved_Models\\1\\CKPlus_1\n",
      "best_acc: 28.000\n",
      "correct_map: [0, 0, 0, 0, 0, 0, 21]\n",
      "\n",
      "------------Epoch: 1-------------\n",
      "learning_rate: 0.008\n",
      "[==============================>] | Time: 58.86s | Loss: 1.891 | Acc: 21.744% (197/906)\n",
      "[==============================>] | Time: 1.19s | Loss: 1.922 | Acc: 28.000% (21/75)\n",
      "\n",
      "------------Epoch: 2-------------\n",
      "learning_rate: 0.008\n",
      "[==============================>] | Time: 59.13s | Loss: 1.874 | Acc: 23.510% (213/906)\n",
      "[==============================>] | Time: 1.26s | Loss: 1.852 | Acc: 28.000% (21/75)\n",
      "\n",
      "------------Epoch: 3-------------\n",
      "learning_rate: 0.008\n",
      "[==============================>] | Time: 59.21s | Loss: 1.843 | Acc: 23.179% (210/906)\n",
      "[==============================>] | Time: 1.23s | Loss: 1.829 | Acc: 28.000% (21/75)\n",
      "\n",
      "------------Epoch: 4-------------\n",
      "learning_rate: 0.008\n",
      "[==============================>] | Time: 59.45s | Loss: 1.830 | Acc: 24.724% (224/906)\n",
      "[==============================>] | Time: 1.25s | Loss: 1.852 | Acc: 28.000% (21/75)\n",
      "Saving Temp Model...\n",
      "\n",
      "------------Epoch: 5-------------\n",
      "learning_rate: 0.008\n",
      "[==============================>] | Time: 59.19s | Loss: 1.817 | Acc: 24.393% (221/906)\n",
      "[==============================>] | Time: 1.20s | Loss: 1.873 | Acc: 20.000% (15/75)\n",
      "\n",
      "------------Epoch: 6-------------\n",
      "learning_rate: 0.008\n",
      "[==============================>] | Time: 59.76s | Loss: 1.819 | Acc: 25.166% (228/906)\n",
      "[==============================>] | Time: 1.27s | Loss: 1.849 | Acc: 20.000% (15/75)\n",
      "\n",
      "------------Epoch: 7-------------\n",
      "learning_rate: 0.008\n",
      "[==============================>] | Time: 59.08s | Loss: 1.811 | Acc: 24.393% (221/906)\n",
      "[==============================>] | Time: 1.22s | Loss: 1.850 | Acc: 28.000% (21/75)\n",
      "\n",
      "------------Epoch: 8-------------\n",
      "learning_rate: 0.008\n",
      "[==============================>] | Time: 58.96s | Loss: 1.820 | Acc: 24.614% (223/906)\n",
      "[==============================>] | Time: 1.23s | Loss: 1.869 | Acc: 28.000% (21/75)\n",
      "\n",
      "------------Epoch: 9-------------\n",
      "learning_rate: 0.008\n",
      "[==============================>] | Time: 59.40s | Loss: 1.821 | Acc: 25.386% (230/906)\n",
      "[==============================>] | Time: 1.23s | Loss: 1.864 | Acc: 16.000% (12/75)\n",
      "Saving Temp Model...\n",
      "\n",
      "------------Epoch: 10-------------\n",
      "learning_rate: 0.008\n",
      "[==============================>] | Time: 59.95s | Loss: 1.805 | Acc: 24.834% (225/906)\n",
      "[==============================>] | Time: 1.22s | Loss: 1.873 | Acc: 28.000% (21/75)\n",
      "\n",
      "------------Epoch: 11-------------\n",
      "learning_rate: 0.008\n",
      "[==============================>] | Time: 58.53s | Loss: 1.832 | Acc: 22.958% (208/906)\n",
      "[==============================>] | Time: 1.20s | Loss: 1.853 | Acc: 24.000% (18/75)\n",
      "\n",
      "------------Epoch: 12-------------\n",
      "learning_rate: 0.008\n",
      "[==============================>] | Time: 58.52s | Loss: 1.840 | Acc: 22.627% (205/906)\n",
      "[==============================>] | Time: 1.22s | Loss: 1.842 | Acc: 28.000% (21/75)\n",
      "\n",
      "------------Epoch: 13-------------\n",
      "learning_rate: 0.008\n",
      "[==============================>] | Time: 58.60s | Loss: 1.834 | Acc: 24.724% (224/906)\n",
      "[==============================>] | Time: 1.24s | Loss: 1.849 | Acc: 28.000% (21/75)\n",
      "\n",
      "------------Epoch: 14-------------\n",
      "learning_rate: 0.008\n",
      "[==============================>] | Time: 58.59s | Loss: 1.844 | Acc: 24.172% (219/906)\n",
      "[==============================>] | Time: 1.22s | Loss: 1.835 | Acc: 28.000% (21/75)\n",
      "Saving Temp Model...\n",
      "\n",
      "------------Epoch: 15-------------\n",
      "learning_rate: 0.008\n",
      "[==============================>] | Time: 58.71s | Loss: 1.832 | Acc: 23.400% (212/906)\n",
      "[==============================>] | Time: 1.21s | Loss: 1.776 | Acc: 29.333% (22/75)\n",
      "Saving net to Saved_Models\\1\\CKPlus_1\n",
      "best_acc: 29.333\n",
      "correct_map: [0, 1, 0, 0, 0, 0, 21]\n",
      "\n",
      "------------Epoch: 16-------------\n",
      "learning_rate: 0.008\n",
      "[==============================>] | Time: 58.47s | Loss: 1.844 | Acc: 23.510% (213/906)\n",
      "[==============================>] | Time: 1.22s | Loss: 1.845 | Acc: 28.000% (21/75)\n",
      "\n",
      "------------Epoch: 17-------------\n",
      "learning_rate: 0.008\n",
      "[==============================>] | Time: 58.53s | Loss: 1.812 | Acc: 23.289% (211/906)\n",
      "[==============================>] | Time: 1.25s | Loss: 1.899 | Acc: 24.000% (18/75)\n",
      "\n",
      "------------Epoch: 18-------------\n",
      "learning_rate: 0.008\n",
      "[==============================>] | Time: 58.94s | Loss: 1.829 | Acc: 25.386% (230/906)\n",
      "[==============================>] | Time: 1.28s | Loss: 1.847 | Acc: 28.000% (21/75)\n",
      "\n",
      "------------Epoch: 19-------------\n",
      "learning_rate: 0.008\n",
      "[==============================>] | Time: 58.48s | Loss: 1.817 | Acc: 24.945% (226/906)\n",
      "[==============================>] | Time: 1.18s | Loss: 1.999 | Acc: 24.000% (18/75)\n",
      "Saving Temp Model...\n",
      "\n",
      "------------Epoch: 20-------------\n",
      "learning_rate: 0.008\n",
      "[==============================>] | Time: 58.73s | Loss: 1.809 | Acc: 26.600% (241/906)\n",
      "[==============================>] | Time: 1.20s | Loss: 1.713 | Acc: 29.333% (22/75)\n",
      "\n",
      "------------Epoch: 21-------------\n",
      "learning_rate: 0.008\n",
      "[==============================>] | Time: 58.24s | Loss: 1.821 | Acc: 25.166% (228/906)\n",
      "[==============================>] | Time: 1.19s | Loss: 1.770 | Acc: 32.000% (24/75)\n",
      "Saving net to Saved_Models\\1\\CKPlus_1\n",
      "best_acc: 32.000\n",
      "correct_map: [0, 3, 0, 0, 0, 0, 21]\n",
      "\n",
      "------------Epoch: 22-------------\n",
      "learning_rate: 0.008\n",
      "[==============================>] | Time: 58.22s | Loss: 1.820 | Acc: 26.600% (241/906)\n",
      "[==============================>] | Time: 1.23s | Loss: 1.803 | Acc: 32.000% (24/75)\n",
      "\n",
      "------------Epoch: 23-------------\n",
      "learning_rate: 0.008\n",
      "[==============================>] | Time: 58.18s | Loss: 1.857 | Acc: 23.510% (213/906)\n",
      "[==============================>] | Time: 1.23s | Loss: 1.844 | Acc: 21.333% (16/75)\n",
      "\n",
      "------------Epoch: 24-------------\n",
      "learning_rate: 0.008\n",
      "[==============================>] | Time: 58.11s | Loss: 1.842 | Acc: 22.958% (208/906)\n",
      "[==============================>] | Time: 1.30s | Loss: 1.863 | Acc: 28.000% (21/75)\n",
      "Saving Temp Model...\n",
      "\n",
      "------------Epoch: 25-------------\n",
      "learning_rate: 0.008\n",
      "[==============================>] | Time: 58.07s | Loss: 1.847 | Acc: 23.400% (212/906)\n",
      "[==============================>] | Time: 1.20s | Loss: 1.860 | Acc: 28.000% (21/75)\n",
      "\n",
      "------------Epoch: 26-------------\n",
      "learning_rate: 0.008\n",
      "[==============================>] | Time: 58.04s | Loss: 1.845 | Acc: 23.620% (214/906)\n",
      "[==============================>] | Time: 1.18s | Loss: 1.854 | Acc: 28.000% (21/75)\n",
      "\n",
      "------------Epoch: 27-------------\n",
      "learning_rate: 0.008\n",
      "[==============================>] | Time: 58.12s | Loss: 1.849 | Acc: 22.848% (207/906)\n",
      "[==============================>] | Time: 1.19s | Loss: 1.850 | Acc: 28.000% (21/75)\n",
      "\n",
      "------------Epoch: 28-------------\n",
      "learning_rate: 0.008\n",
      "[==============================>] | Time: 58.29s | Loss: 1.845 | Acc: 23.400% (212/906)\n",
      "[==============================>] | Time: 1.21s | Loss: 1.844 | Acc: 28.000% (21/75)\n",
      "\n",
      "------------Epoch: 29-------------\n",
      "learning_rate: 0.008\n",
      "[==============================>] | Time: 58.72s | Loss: 1.840 | Acc: 22.185% (201/906)\n",
      "[==============================>] | Time: 1.23s | Loss: 1.853 | Acc: 28.000% (21/75)\n",
      "Saving Temp Model...\n",
      "\n",
      "------------Epoch: 30-------------\n",
      "learning_rate: 0.008\n",
      "[==============================>] | Time: 59.41s | Loss: 1.842 | Acc: 23.289% (211/906)\n",
      "[==============================>] | Time: 1.26s | Loss: 1.860 | Acc: 28.000% (21/75)\n",
      "\n",
      "------------Epoch: 31-------------\n",
      "learning_rate: 0.008\n",
      "[==============>...............] | Time: 28.88s | Loss: 1.859 | Acc: 25.231% (109/432)"
     ]
    },
    {
     "ename": "KeyboardInterrupt",
     "evalue": "",
     "output_type": "error",
     "traceback": [
      "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m",
      "\u001b[1;31mKeyboardInterrupt\u001b[0m                         Traceback (most recent call last)",
      "\u001b[1;32m<ipython-input-7-1176ae7ba560>\u001b[0m in \u001b[0;36m<module>\u001b[1;34m()\u001b[0m\n\u001b[0;32m     10\u001b[0m     \u001b[1;32mfor\u001b[0m \u001b[0mepoch\u001b[0m \u001b[1;32min\u001b[0m \u001b[0mrange\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mstart_epoch\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mopt\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mepoch\u001b[0m\u001b[1;33m,\u001b[0m \u001b[1;36m1\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m     11\u001b[0m         \u001b[0mprint\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;34m'\\n------------Epoch: %d-------------'\u001b[0m \u001b[1;33m%\u001b[0m \u001b[0mepoch\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m---> 12\u001b[1;33m         \u001b[0mtrain\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mepoch\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m     13\u001b[0m         \u001b[0mtest\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mepoch\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m     14\u001b[0m         \u001b[0mtemp_internal\u001b[0m \u001b[1;33m-=\u001b[0m \u001b[1;36m1\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n",
      "\u001b[1;32m<ipython-input-6-6781c9e45cfc>\u001b[0m in \u001b[0;36mtrain\u001b[1;34m(epoch)\u001b[0m\n\u001b[0;32m     39\u001b[0m         \u001b[0mcorrect\u001b[0m \u001b[1;33m+=\u001b[0m \u001b[0mpredicted\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0meq\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mground_value\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mdata\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mcpu\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0msum\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m     40\u001b[0m         \u001b[1;31m# print(\"equal: \", predicted.eq(ground_value.data).cpu())\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m---> 41\u001b[1;33m         \u001b[0mcur_train_acc\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mfloat\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mcorrect\u001b[0m\u001b[1;33m)\u001b[0m \u001b[1;33m/\u001b[0m \u001b[0mfloat\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mtotal\u001b[0m\u001b[1;33m)\u001b[0m \u001b[1;33m*\u001b[0m \u001b[1;36m100.\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m     42\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m     43\u001b[0m         \u001b[0mtime_end\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mtime\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mtime\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n",
      "\u001b[1;31mKeyboardInterrupt\u001b[0m: "
     ]
    }
   ],
   "source": [
    "# 创建存储模型的文件夹\n",
    "if not os.path.isdir(net_to_save_dir):\n",
    "    os.mkdir(net_to_save_dir)\n",
    "if not os.path.isdir(os.path.join(net_to_save_dir, str(opt.save_number))):\n",
    "    os.mkdir(os.path.join(net_to_save_dir, str(opt.save_number)))\n",
    "if not os.path.isdir(net_to_save_path):\n",
    "    os.mkdir(net_to_save_path)\n",
    "    \n",
    "if not over_flag:\n",
    "    for epoch in range(start_epoch, opt.epoch, 1):\n",
    "        print('\\n------------Epoch: %d-------------' % epoch)\n",
    "        train(epoch)\n",
    "        test(epoch)\n",
    "        temp_internal -= 1\n",
    "        if temp_internal <= 0:\n",
    "            temp_internal = TEMP_EPOCH\n",
    "            print(\"Saving Temp Model...\")\n",
    "            state = {'net': net.state_dict() if use_cuda else net,\n",
    "                     'best_test_acc': test_acc_map['best_acc'],\n",
    "                     'best_test_acc_epoch': test_acc_map['best_acc_epoch'],\n",
    "                     'best_train_acc': train_acc_map['best_acc'],\n",
    "                     'best_train_acc_epoch': train_acc_map['best_acc_epoch'],\n",
    "                     'cur_epoch': epoch,\n",
    "                     }\n",
    "            torch.save(state, os.path.join(net_to_save_path, saved_temp_model_name))\n",
    "    print(train_acc_map)\n",
    "    print(test_acc_map)\n",
    "    save_over_flag()\n",
    "print(\"Trained Over\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.6.3"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
